<template>
  <q-select
    :id="'tree-' + field.name"
    filled
    use-input
    hide-selected
    fill-input
    v-model="serialization"
    clearable
    :options="selectOptions"
    :label="field.label"
    lazy-rules
    :rules="field.rules ? field.rules : null"
    ref="select"
    input-debounce="500"
    @filter="selectFilterFn"
    @popup-show="popupShow"
    @popup-hide="popupHide"
    @clear="onClear"
    v-bind="$attrs"
  >
    <template v-slot:option>
      <q-tree
        ref="tree"
        :nodes="treeOptions"
        :dense="dense"
        :node-key="nodeKey"
        v-model:selected="treeSelected"
      />
    </template>
    <template v-slot:hint v-if="field.hint || field.compare">
      <div class="text-bold text-white bg-yellow-10" style="padding: 1px;" v-if="canShowCompare">
        {{field.compare.label ? field.compare.label + '：' : ''}}{{field.compare.map ? showCompareValue(field.compare.map.value) : showCompareValue(field.compare.value)}}
      </div>
      <div v-if="field.hint">{{field.hint}}</div>
    </template>
  </q-select>
</template>
<script>
import { defineComponent } from 'vue';
import pinyin from 'src/lib/vue-py';

export default defineComponent({
  name: 'fieldTreeSelect',
  props: {
    field: {
      type: Object,
      default: () => []
    }
  },
  data () {
    return {
      selectOptions: [''],

      treeSelected: null,
      treeFieldWord: '',
      treeOptions: [],

      flag: true
    }
  },
  methods: {
    selectFilterFn (val, update) {
      this.treeFieldWord = String(val || '').trim();

      if (this.treeFieldWord) {
        const treeFilter = String(this.treeFieldWord).toLowerCase().trim();
        const key = this.nodeKey;
        const index = this.labelIndex;
        const nodeStack = [];
        // 遍历树field.options，根据过滤词查找节点，找到后只保留当前节点及父节点
        function findNode (nodes, word, path, stack) {
          for (const node of nodes) {
            const py = pinyin.chineseToPinYin(node[index], true).toLowerCase() || '';
            const label = String(node[index] || '');
            const nodePath = [...path, String(node[key])];
            if (label.toLowerCase().indexOf(word) > -1 || py.indexOf(word) > -1) {
              stack.push(nodePath);
            }

            if (node.children && node.children.length > 0) {
              findNode(node.children, word, nodePath, stack);
            }
          }
        }
        findNode(this.field.options, treeFilter, [], nodeStack);

        // 符合条件的节点及其路径id
        const ids = [...new Set(nodeStack.flat())];

        // 过滤出节点
        function filterTree (nodes) {
          const filterNodes = nodes.filter(node => ids.includes(String(node[key])));
          for (const node of filterNodes) {
            if (node.children && node.children.length > 0) {
              node.children = filterTree(node.children);
            }
          }
          return filterNodes;
        }
        this.treeOptions = filterTree(JSON.parse(JSON.stringify(this.field.options)));
      } else {
        this.treeOptions = this.field.options;
      }

      update(() => {
        // 这里必须写，否则option插槽不刷新
        this.selectOptions = [''];
        this.$nextTick(() => {
          this.$refs.tree && this.$refs.tree.expandAll();
        });
      });
    },
    popupShow () {
      this.flag = true;

      if (this.field.expandAll) {
        setTimeout(() => {
          this.$refs.tree && this.$refs.tree.expandAll();
        }, 300);
      } else if (this.field.includeRoot) {
        setTimeout(() => {
          this.$refs.tree && this.$refs.tree.setExpanded(this.field.options[0][this.nodeKey], true);
        }, 300);
      }
    },
    popupHide () {
      this.flag = false;
      this.treeSelected = null;
    },
    onClear () {
      this.field.value = '';
    }
  },
  computed: {
    readonly () {
      return !!this.field.readonly;
    },
    dense () {
      return !!this.field.dense;
    },
    nodeKey () {
      return this.field.key || 'value';
    },
    labelIndex () {
      return this.field.index || 'label';
    },
    canShowCompare () {
      /*
        compare的值
        compare: {
          label, // 标题
          value, // 对比的值
          always // true-有数据就显示 false-值不同，再显示
        } */
      let compareValue, fieldValue = '';
      if (this.field.compare) {
        compareValue = typeof this.field.compare.value === 'object' && this.field.compare.value != null ? this.field.compare.value.value : this.field.compare.value;
        fieldValue = typeof this.field.value === 'object' && this.field.value !== null ? this.field.value.value : this.field.value;
      }

      return this.field.compare && this.field.compare.value !== null && (this.field.compare.always || compareValue != fieldValue);
    },
    serialization () {
      function findNodePath (root, targetId, key) {
        // 辅助函数，用于递归查找
        function search (node, path) {
          if (node[key] === targetId) {
            return [...path, node];
          }

          if (node.children && node.children.length > 0) {
            for (const child of node.children) {
              const result = search(child, [...path, node]);
              if (result) {
                return result;
              }
            }
          }
          return null;
        }

        return search(root, []);
      }

      if (this.field.value !== '' && this.field.options.length > 0) {
        let path = null;
        if (this.field.includeRoot) {
          path = findNodePath(this.field.options[0], this.field.value, this.nodeKey);
        } else {
          path = findNodePath({ [this.nodeKey]: 0, children: this.field.options }, this.field.value, this.nodeKey);
          path = path.slice(1);
        }
        return path ? path.map(v => v[this.labelIndex]).join('-') : '';
      } else {
        return '';
      }
    }
  },
  watch: {
    treeSelected (val) {
      if (this.flag) {
        this.field.value = val;
        this.$refs.select.hidePopup();
      }
    },
    'field.options' (val) {
      this.treeOptions = val;
    }
  }
});
</script>
